package com.lyc.utils.bd;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringReader;
import java.security.*;

/**
 * 签名相关的工具类
 * @version 1.0.0
 *
 */
public class SignatureUtils {
    private static Logger logger = LoggerFactory.getLogger(SignatureUtils.class);
    
    static {
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }
    
    /**
     * 读取pubKey
     * @param pemKey
     * @return
     */
    public static PublicKey parsePEMPublicKey(String pemKey) {
        PEMReader reader = new PEMReader(new StringReader(pemKey));
        Object key;
        try {
            key = reader.readObject();
            reader.close();
        } catch (IOException e) {
            logger.error("read pubKey error, pemKey: {}", pemKey);
            throw new ParsePemKeyException();
        }

        if (key instanceof PublicKey) {
            PublicKey publicKey = (PublicKey) key;
            return publicKey;
        }
        logger.error("not a public key, pemKey: {}", pemKey);
        throw new ParsePemKeyException();
    }
    
    /**
     * 读取privateKey
     * @param pemKey
     * @return
     */
    public static PrivateKey parsePEMPrivateKey(String pemKey) {
        PEMReader reader = new PEMReader(new StringReader(pemKey));
        Object key;
        try {
            key = reader.readObject();
            reader.close();
        } catch (IOException e) {
            logger.error("read pubKey error, pemKey: {}", pemKey);
            throw new ParsePemKeyException();
        }

        if (key instanceof KeyPair) {
            PrivateKey privateKey = ((KeyPair) key).getPrivate();
            return privateKey;
        }
        logger.error("not a private key, pemKey: {}", pemKey);
        throw new ParsePemKeyException();
    }
    
    /**
     * 签名信息
     * @param privateKey
     * @param message
     * @return
     */
    public static byte[] signMessage(PrivateKey privateKey, byte[] message) {
        Assert.notNull(privateKey);
        Assert.notNull(message);
        
        Signature dsa;
        try {
            dsa = Signature.getInstance("SHA1withDSA", "SUN");
            dsa.initSign(privateKey);
            dsa.update(message);
            byte[] result = dsa.sign();
            return result;
        } catch (Exception e) {
            logger.error("sign error, stack trace: ",  e);
            throw new SignMessageException();
        }
    }
    
    /**
     * 验证签名数据
     * @param pubKey
     * @param message
     * @param signature
     * @return
     */
    public static boolean verifySignature(PublicKey pubKey, byte[] message, byte[] signature) {
        Signature dsa;
        try {
            dsa = Signature.getInstance("SHA1withDSA", "SUN");
            dsa.initVerify(pubKey);
            dsa.update(message);
            return dsa.verify(signature);
        } catch (Exception e) {
            logger.error("verify signature error, stack trace: ", e);
        }
        return false; 
    }
}
